﻿using System;
using CTS.Com.Domain.Exceptions;
using CTS.Com.Domain.Helper;
using CTS.Com.Domain.Validate.Model;

namespace CTS.Com.Domain.Validate.Attr
{
    public class DomainValidation : AbstractValidation
    {
        public string RuleName { get; set; }

        public override void IsValid(object input, Rule rule)
        {
            // Convert string
            var data = Convert.ToString(input);

            if (rule.StringType != null) {
                String(data, rule);
            }
            if (rule.IntegerType != null) {
                Integer(data, rule);
            }
            if (rule.RealType != null) {
                Real(data, rule);
            }
            if (rule.BooleanType != null) {
                Boolean(data, rule);
            }
            if (rule.DateType != null) {
                Date(data, rule);
            }
            if (rule.EmailType != null) {
                Email(data, rule);
            }
        }

        private void String(string input, Rule rule)
        {
            // Convert input
            var value = DataHelper.ConvertInputString(input);
            var length = decimal.Zero;

            // Check required
            if (Required && DataCheckHelper.IsNull(value)) {
                throw new ExecuteException("E_MSG_00001", MessageParam);
            }

            // Get length
            if (!DataCheckHelper.IsNull(value)) {
                length = value.Length;
            }

            // Check min character
            if (!DataCheckHelper.IsNull(rule.StringType.MinLength)
                && length < rule.StringType.MinLength) {
                throw new ExecuteException("E_MSG_00002", MessageParam, rule.StringType.MinLength);
            }

            // Check max character
            if (!DataCheckHelper.IsNull(rule.StringType.MaxLength)
                && length > rule.StringType.MaxLength) {
                throw new ExecuteException("E_MSG_00003", MessageParam, rule.StringType.MaxLength);
            }
        }

        private void Integer(string input, Rule rule)
        {
            // Check number
            if (!DataCheckHelper.IsNumber(input)) {
                throw new ExecuteException("E_MSG_00004", MessageParam);
            }

            // Convert input
            var value = DataHelper.ConvertInputNumber(input);

            // Check integer
            if (!DataCheckHelper.IsInteger(input)) {
                throw new ExecuteException("E_MSG_00006", MessageParam);
            }

            // Check required
            if (Required && DataCheckHelper.IsNull(value)) {
                throw new ExecuteException("E_MSG_00001", MessageParam);
            }

            // Check min
            if (!DataCheckHelper.IsNull(rule.IntegerType.Min) && value < rule.IntegerType.Min) {
                throw new ExecuteException("E_MSG_00011", MessageParam, rule.IntegerType.Min);
            }

            // Check max
            if (!DataCheckHelper.IsNull(rule.IntegerType.Max) && value > rule.IntegerType.Max) {
                throw new ExecuteException("E_MSG_00012", MessageParam, rule.IntegerType.Max);
            }
        }

        private void Real(string input, Rule rule)
        {
            // Check number
            if (!DataCheckHelper.IsNumber(input)) {
                throw new ExecuteException("E_MSG_00004", MessageParam);
            }

            // Convert input
            var value = DataHelper.ConvertInputNumber(input);

            // Check integer
            if (!DataCheckHelper.IsReal(input)) {
                throw new ExecuteException("E_MSG_00006", MessageParam);
            }

            // Check required
            if (Required && DataCheckHelper.IsNull(value)) {
                throw new ExecuteException("E_MSG_00001", MessageParam);
            }

            // Check min
            if (!DataCheckHelper.IsNull(rule.RealType.Min) && value < rule.RealType.Min) {
                throw new ExecuteException("E_MSG_00011", MessageParam, rule.RealType.Min);
            }

            // Check max
            if (!DataCheckHelper.IsNull(rule.RealType.Max) && value > rule.RealType.Max) {
                throw new ExecuteException("E_MSG_00012", MessageParam, rule.RealType.Max);
            }
        }

        private void Date(string data, Rule rule)
        {
            // Check date
            if (!DataCheckHelper.IsDate(data)) {
                throw new ExecuteException("E_MSG_00005", MessageParam);
            }

            // Convert input
            var value = DataHelper.ConvertInputDate(data);

            // Check required
            if (Required && DataCheckHelper.IsNull(value)) {
                throw new ExecuteException("E_MSG_00001", MessageParam);
            }
        }

        private void Email(string data, Rule rule)
        {
            // Convert input
            var value = DataHelper.ConvertInputString(data);

            // Check email
            if (!DataCheckHelper.IsEmail(value)) {
                throw new ExecuteException("E_MSG_00006", MessageParam);
            }

            // Check required
            if (Required && DataCheckHelper.IsNull(value)) {
                throw new ExecuteException("E_MSG_00001", MessageParam);
            }
        }

        private void Boolean(string data, Rule rule)
        {
            // Check boolean
            if (!DataCheckHelper.IsBoolean(data)) {
                throw new ExecuteException("E_MSG_00013", MessageParam);
            }

            // Convert input
            var value = DataHelper.ConvertInputBoolean(data);

            // Check required
            if (Required && DataCheckHelper.IsNull(value)) {
                throw new ExecuteException("E_MSG_00001", MessageParam);
            }
        }
    }
}
